package org.budo.support.mvcs;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.budo.support.assertion.Assert;
import org.budo.support.java.collection.wrapper.NiceToStringMapWrapper;
import org.budo.support.lang.util.ArrayUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.NumberUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.servlet.util.QueryStringUtil;
import org.budo.support.servlet.util.RequestUtil;
import org.budo.support.servlet.util.ResponseUtil;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * TODO 尝试 使用 RequestContextListener 然后去除其他Request
 * 
 * @author limingwei2
 * @see org.budo.support.mvcs.MvcsHandlerInterceptor
 * @see org.budo.support.mvcs.MvcsFilter
 */
public class Mvcs {
    private static final Logger log = Slf4j.getLogger();

    private static final ThreadLocal<HttpServletRequest> REQUEST_THREAD_LOCAL = new InheritableThreadLocal<HttpServletRequest>();

    private static final ThreadLocal<HttpServletResponse> RESPONSE_THREAD_LOCAL = new InheritableThreadLocal<HttpServletResponse>();

    /**
     * spring 4.0.5 没有这个方法
     */
    private static final boolean SERVLET_REQUEST_ATTRIBUTES_HAS_GET_RESPONSE_METHOD = ReflectUtil.hasMethod(ServletRequestAttributes.class, "getResponse", new Class[0]);

    /**
     * 注意，调用 setThreadLocal 之后，应当调用 removeThreadLocal 作对应的清理
     * 
     * @see #removeThreadLocal()
     */
    public static void setThreadLocal(ServletRequest request, ServletResponse response) {
        Assert.notNull(request, "#56 setRequest no null");
        REQUEST_THREAD_LOCAL.set((HttpServletRequest) request);

        Assert.notNull(response, "#59 setResponse no null");
        RESPONSE_THREAD_LOCAL.set((HttpServletResponse) response);
    }

    public static void removeThreadLocal() {
        REQUEST_THREAD_LOCAL.remove();
        RESPONSE_THREAD_LOCAL.remove();
    }

    public static Object getHandler() {
        Object handler = MvcsHandlerInterceptor.getHandler();
        return handler;
    }

    public static HttpServletResponse getResponse() {
        HttpServletResponse response = null;

        // 优先级顺序
        response = RESPONSE_THREAD_LOCAL.get();
        if (null != response) {
            return response;
        }

        response = MvcsHandlerInterceptor.getResponse();
        if (null != response) {
            return response;
        }

        response = MvcsFilter.getResponse();
        if (null != response) {
            return response;
        }

        response = getResponseBySpringHolder();
        if (null != response) {
            return response;
        }

        if (null == response) {
            log.warn("#80 getResponse() returns null, requestAttributes=" + RequestContextHolder.getRequestAttributes());
        }

        return response;
    }

    public static HttpServletRequest getRequest() {
        HttpServletRequest request = null;

        // 优先级顺序
        request = REQUEST_THREAD_LOCAL.get();
        if (null != request) {
            return request;
        }

        request = MvcsHandlerInterceptor.getRequest();
        if (null != request) {
            return request;
        }

        request = MvcsFilter.getRequest();
        if (null != request) {
            return request;
        }

        request = getRequestBySpringHolder();
        if (null != request) {
            return request;
        }

        if (null == request) {
            log.warn("#99 getRequest() returns null, requestAttributes=" + RequestContextHolder.getRequestAttributes());
        }

        return request;
    }

    private static HttpServletResponse getResponseBySpringHolder() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (null != requestAttributes //
                && SERVLET_REQUEST_ATTRIBUTES_HAS_GET_RESPONSE_METHOD) {
            if (requestAttributes instanceof ServletRequestAttributes) {
                return ((ServletRequestAttributes) requestAttributes).getResponse();
            }
        }

        return null;
    }

    /**
     * 获取到的是最初的Request，可能会有Session取不到值的情况，应该作为最低优先级
     */
    private static HttpServletRequest getRequestBySpringHolder() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (null != requestAttributes) {
            if (requestAttributes instanceof ServletRequestAttributes) {
                return ((ServletRequestAttributes) requestAttributes).getRequest();
            }
        }

        return null;
    }

    public static HttpSession getSession() {
        HttpServletRequest request = getRequest();

        if (null == request) {
            log.error("#111 getSession error, request is null, request=" + request);
            return null;
        }

        return request.getSession();
    }

    public static String getSessionId() {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#122 getSessionId error, session is null");
            return null;
        }

        return session.getId();
    }

    public static void setSessionAttribute(String key, Object value) {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#133 setSessionAttribute error, session is null, key=" + key + ", value=" + value);
            return;
        }

        session.setAttribute(key, value);
    }

    public static Object getSessionAttribute(String key) {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#144 getSessionAttribute error, session is null, key=" + key);
            return null;
        }

        return session.getAttribute(key);
    }

    public static Map<String, Object> getSessionAttributeMap() {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#155 getSessionAttributeMap error, session is null");
            return null;
        }

        Map<String, Object> map = new HashMap<String, Object>();
        Enumeration<String> enumeration = session.getAttributeNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            Object value = session.getAttribute(key);
            map.put(key, value);
        }

        return new NiceToStringMapWrapper(map);
    }

    public static void removeSessionAttribute(String key) {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#174 removeSessionAttribute error, session is null, key=" + key);
            return;
        }

        session.removeAttribute(key);
    }

    public static void setRequestAttribute(String key, Object value) {
        HttpServletRequest request = getRequest();

        if (null == request) {
            log.error("#185 setRequestAttribute error, request is null, key=" + key + ", value=" + value);
            return;
        }

        request.setAttribute(key, value);
    }

    public static Object getRequestAttribute(String key) {
        HttpServletRequest request = getRequest();

        if (null == request) {
            log.error("#196 getRequestAttribute error, request is null, key=" + key);
            return null;
        }

        Object attribute = request.getAttribute(key);
        return attribute;
    }

    public static Map<String, String[]> getRequestParameterMap() {
        HttpServletRequest request = getRequest();
        return getRequestParameterMap(request);
    }

    public static Map<String, String[]> getRequestParameterMap(ServletRequest request) {
        if (null == request) {
            log.error("#211 getRequestParameterMap error, request is null");
            return null;
        }

        Map<String, String[]> parameterMap = request.getParameterMap();
        return new NiceToStringMapWrapper(parameterMap);
    }

    public static String getRequestParameter(String key) {
        HttpServletRequest request = getRequest();
        return getRequestParameter(request, key);
    }

    public static String getRequestParameter(HttpServletRequest request, String key) {
        if (null == request || null == key) {
            log.error("#223 getRequestParameter error, request is null, request=" + request + ", key=" + key);
            return null;
        }

        String value = request.getParameter(key);
        if (!StringUtil.isEmpty(value)) {
            return value;
        }

        // 项目中有出现过 getParameter 获取不到，但 queryString 有值的情况，不知具体原因
        String queryString = request.getQueryString();
        Map<String, String[]> queryStringMap = QueryStringUtil.queryStringToMap(queryString);
        String[] queryValue = queryStringMap.get(key);
        if (!ArrayUtil.isEmpty(queryValue)) {
            return queryValue[0];
        }

        return value;
    }

    public static Map<String, String[]> getRequestHeaderMap(ServletRequest request) {
        if (null == request) {
            log.error("#247 getRequestHeaderMap error, request is null, request=" + request);
            return null;
        }

        Map<String, String[]> map = new HashMap<String, String[]>();

        Enumeration<String> enumeration = ((HttpServletRequest) request).getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String[] values = getRequestHeaders((HttpServletRequest) request, key);
            map.put(key, values);
        }

        return new NiceToStringMapWrapper(map);
    }

    public static Map<String, String[]> getRequestHeaderMap() {
        HttpServletRequest request = getRequest();
        return getRequestHeaderMap(request);
    }

    public static String[] getRequestHeaders(HttpServletRequest request, String key) {
        if (null == request) {
            log.error("#273 getRequestHeaders error, request is null, key=" + key);
            return null;
        }

        List<String> values = new ArrayList<String>();

        Enumeration<String> enumeration = request.getHeaders(key);
        while (enumeration.hasMoreElements()) {
            values.add(enumeration.nextElement());
        }

        return values.toArray(new String[values.size()]);
    }

    public static String[] getRequestHeaders(String key) {
        HttpServletRequest request = getRequest();
        return getRequestHeaders(request, key);
    }

    public static Map<String, Object> getRequestAttributeMap(HttpServletRequest request) {
        if (null == request) {
            log.error("#289 getRequestAttributeMap error, request is null");
            return null;
        }

        Enumeration<String> enumeration = request.getAttributeNames();
        Map<String, Object> map = new HashMap<String, Object>();

        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            Object value = request.getAttribute(key);
            map.put(key, value);
        }

        return new NiceToStringMapWrapper(map);
    }

    public static Map<String, Object> getRequestAttributeMap() {
        HttpServletRequest request = getRequest();
        return getRequestAttributeMap(request);
    }

    public static String getRequestBody() {
        HttpServletRequest request = getRequest();
        return getRequestBody(request);
    }

    public static String getRequestBody(ServletRequest request) {
        ServletInputStream inputStream = getInputStream(request);
        return IoUtil.toString(inputStream, "UTF-8");
    }

    public static ServletInputStream getInputStream(ServletRequest request) {
        if (null == request) {
            return null;
        }

        try {
            return request.getInputStream();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static ServletInputStream getInputStream() {
        HttpServletRequest request = getRequest();
        return getInputStream(request);
    }

    public static ServletOutputStream getResponseOutputStream() {
        HttpServletResponse response = getResponse();
        return getResponseOutputStream(response);
    }

    public static ServletOutputStream getResponseOutputStream(HttpServletResponse response) {
        try {
            return response.getOutputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getRequestURI() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getRequestURI();
    }

    public static String getScheme() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getScheme();
    }

    public static Integer getServerPort() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getServerPort();
    }

    public static String getServerName() {
        HttpServletRequest request = getRequest();
        return getServerName(request);
    }

    public static String getServerName(HttpServletRequest request) {
        if (null == request) {
            log.error("#372 getServerName error, request is null");
            return null;
        }

        try {
            return request.getServerName();
        } catch (Throwable e) {
            throw new IllegalStateException("request=" + request, e);
        }
    }

    public static void invalidateSession() {
        HttpSession session = getSession();

        if (null == session) {
            log.error("#387 invalidateSession error, session is null");
            return;
        }

        session.invalidate();
    }

    public static String getRequestContextPath() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getContextPath();
    }

    public static StringBuffer getRequestURL() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getRequestURL();
    }

    public static String getReferer(HttpServletRequest request) {
        if (null == request) {
            return null;
        }

        String header = request.getHeader("referer");
        if (!StringUtil.isEmpty(header)) {
            return header;
        }

        return request.getHeader("Referer");
    }

    public static String getReferer() {
        HttpServletRequest request = getRequest();
        return getReferer(request);
    }

    public static String getRequestedSessionId() {
        HttpServletRequest request = getRequest();
        return null == request ? null : request.getRequestedSessionId();
    }

    public static void setContentType(String type) {
        HttpServletResponse response = getResponse();
        if (null == response) {
            log.error("#430 setContentType error, response is null");
        }
        response.setContentType(type);
    }

    public static void sendError(Integer statusCode, String descriptiveMessage) {
        HttpServletResponse response = getResponse();
        ResponseUtil.sendError(response, statusCode, descriptiveMessage);
    }

    public static Long getRequestParameterLong(String key) {
        String value = getRequestParameter(key);
        return NumberUtil.toLong(value);
    }

    public static String getRequestParameter(String key, String defaultValue) {
        String value = getRequestParameter(key);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        }

        return value;
    }

    public static void redirect(String location) {
        HttpServletResponse response = getResponse();

        if (null == response) {
            log.error("#458 forward error, response=" + response + ", location=" + location);
            return;
        }

        ResponseUtil.sendRedirect(response, location);
    }

    public static void forward(String path) {
        HttpServletRequest request = getRequest();
        HttpServletResponse response = getResponse();

        if (null == request || null == response) {
            log.error("#470 forward error, request=" + request + ", response=" + response + ", path=" + path);
            return;
        }

        RequestUtil.forward(path, request, response);
    }

    public static Boolean isPost() {
        HttpServletRequest request = getRequest();

        if (null == request) {
            log.error("#482 forward error, request=" + request);
            return false;
        }

        String method = request.getMethod();
        return StringUtil.equalsIgnoreCase("POST", method);
    }

    public static ServletContext getServletContext() {
        HttpServletRequest request = getRequest();

        if (null == request) {
            log.error("#494 getServletContext error, request is null");
            return null;
        }

        return request.getSession().getServletContext();
    }

    public static InputStream getResourceAsStream(String path) {
        ServletContext servletContext = getServletContext();

        if (null == servletContext) {
            log.error("#505 getResourceAsStream error, servletContext is null, path=" + path);
            return null;
        }

        return servletContext.getResourceAsStream(path);
    }

    public static String getRealPath(String path) {
        ServletContext servletContext = getServletContext();

        if (null == servletContext) {
            log.error("#516 getRealPath error, servletContext is null, path=" + path);
            return null;
        }

        return servletContext.getRealPath(path);
    }

    public static Object getServletContextAttribute(String name) {
        ServletContext servletContext = getServletContext();

        if (null == servletContext) {
            log.error("#527 getServletContextAttribute error, servletContext is null, name=" + name);
            return null;
        }

        return servletContext.getAttribute(name);
    }

    public static void setServletContextAttribute(String key, Object value) {
        ServletContext servletContext = getServletContext();

        if (null == servletContext || null == key) {
            log.error("#538 setServletContextAttribute error, servletContext or key is null, key=" + key + ", value=" + value);
            return;
        }

        servletContext.setAttribute(key, value);
    }

    public static void removeServletContextAttribute(String key) {
        ServletContext servletContext = getServletContext();

        if (null == servletContext || null == key) {
            log.error("#549 removeServletContextAttribute error, servletContext or key is null, key=" + key);
            return;
        }

        servletContext.removeAttribute(key);
    }

    public static String getMethod(ServletRequest request) {
        if (null == request) {
            log.error("#560 getMethod error, request is null");
            return null;
        }

        return ((HttpServletRequest) request).getMethod();
    }

    public static String getMethod() {
        return getMethod(getRequest());
    }

    public static ServletOutputStream getOutputStream() {
        HttpServletResponse response = getResponse();

        if (null == response) {
            log.error("#574 getOutputStream error, request is null");
            return null;
        }

        ServletOutputStream outputStream = getOutputStream(response);
        return outputStream;
    }

    public static ServletOutputStream getOutputStream(ServletResponse response) {
        try {
            return response.getOutputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getRequestURI(ServletRequest request) {
        if (null == request) {
            log.error("#589 getRequestURI error, request is null");
            return null;
        }

        return ((HttpServletRequest) request).getRequestURI();
    }

    public static String requestToString(ServletRequest request) {
        return requestToString(request, true);
    }

    private static String requestToString(ServletRequest request, Boolean withCookie) {
        if (null == request) {
            return "request=null";
        }

        String str = "request=" + request.getClass().getName() + "@" + Integer.toHexString(request.hashCode()) //
                + ", URI=" + getRequestURI(request);

        if (null != withCookie && withCookie) {
            Cookie[] cookies = getRequestCookies((HttpServletRequest) request);
            str += "cookies=" + cookieToString(cookies);
        }

        if (request instanceof HttpServletRequestWrapper) {
            HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper) request;
            str += ", wrappered=" + requestToString(wrapper.getRequest(), false);
        }

        return str;
    }

    private static String cookieToString(Cookie[] cookies) {
        if (null == cookies) {
            return "null";
        }

        String str = "[";
        for (int i = 0; i < cookies.length; i++) {
            if (i > 0) {
                str += ",";
            }

            if (null == cookies[i]) {
                str += "null";
            } else {
                str += cookies[i].getName() + "=" + cookies[i].getValue();
            }
        }
        str += "]";
        return str;
    }

    public static String getUserAgent() {
        return getRequestHeader("User-Agent");
    }

    public static String getUserAgent(ServletRequest request) {
        return getRequestHeader(request, "User-Agent");
    }

    public static String getRequestHeader(ServletRequest request, String key) {
        if (null == request || null == key || !(request instanceof HttpServletRequest)) {
            log.error("#682 getRequestHeader error, request or key is null, request=" + request + ", key=" + key);
            return null;
        }

        return ((HttpServletRequest) request).getHeader(key);
    }

    public static String getRequestHeader(String key) {
        HttpServletRequest request = getRequest();
        return getRequestHeader(request, key);
    }

    public static Map<String, Object> getServletContextAttributes(ServletContext servletContext) {
        Map<String, Object> attributes = new HashMap<String, Object>();
        Enumeration<String> attributeNames = servletContext.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            String attributeName = attributeNames.nextElement();
            attributes.put(attributeName, servletContext.getAttribute(attributeName));
        }
        return attributes;
    }

    public static String getRemoteAddr() {
        HttpServletRequest request = getRequest();
        return getRemoteAddr(request);
    }

    public static String getRemoteAddr(ServletRequest request) {
        return null == request ? null : request.getRemoteAddr();
    }

    public static Integer getRequestHeaderInteger(String key) {
        return getRequestHeaderInteger(getRequest(), key, null);
    }

    public static Integer getRequestHeaderInteger(ServletRequest request, String key, Integer defaultValue) {
        String value = getRequestHeader(key);

        if (StringUtil.isEmpty(value) || value.trim().isEmpty() || "null".equalsIgnoreCase(value)) {
            return defaultValue;
        }

        try {
            return new Integer(value);
        } catch (Throwable e) {
            String message = "#758 getRequestHeaderInteger error, key=" + key + ", value=" + value //
                    + ", UserAgent=" + getUserAgent() + ", RemoteAddr=" + getRemoteAddr() //
                    + ", ServerName=" + getServerName() + ", RequestURI=" + getRequestURI() //
                    + ", e=" + e;

            log.error(message, e);

            throw new RuntimeException(message);
        }
    }

    public static Integer getRequestParameterInteger(ServletRequest request, String key, Integer defaultValue) {
        String value = getRequestParameter(key);

        if (StringUtil.isEmpty(value) || value.trim().isEmpty() || "null".equalsIgnoreCase(value)) {
            return defaultValue;
        }

        try {
            return new Integer(value);
        } catch (Throwable e) {
            String message = "#793 getRequestParameterInteger error, key=" + key + ", value=" + value //
                    + ", UserAgent=" + getUserAgent() + ", RemoteAddr=" + getRemoteAddr() //
                    + ", ServerName=" + getServerName() + ", RequestURI=" + getRequestURI() //
                    + ", e=" + e;

            log.error(message, e);

            throw new RuntimeException(message);
        }
    }

    public static Integer getRequestParameterInteger(String key, Integer defaultValue) {
        HttpServletRequest request = getRequest();
        return getRequestParameterInteger(request, key, defaultValue);
    }

    public static Integer getRequestParameterInteger(HttpServletRequest request, String key) {
        return getRequestParameterInteger(request, key, null);
    }

    public static Integer getRequestParameterInteger(String key) {
        HttpServletRequest request = getRequest();
        return getRequestParameterInteger(request, key, null);
    }

    public static void addCookie(HttpServletResponse response, String name, String value) {
        addCookie(response, name, value, null);
    }

    /**
     * @param expiry 秒
     */
    public static void addCookie(String name, String value, Integer expiry) {
        HttpServletResponse response = getResponse();
        addCookie(response, name, value, expiry);
    }

    public static void addCookie(String name, String value) {
        addCookie(name, value, null);
    }

    public static void removeCookie(String name) {
        HttpServletResponse response = getResponse();
        removeCookie(response, name);
    }

    /**
     * cookie.path 不同的，不能删除
     */
    public static void removeCookie(HttpServletResponse response, String name) {
        if (null == response || StringUtil.isEmpty(name)) {
            log.error("#762 removeCookie error, response=" + response + ", name=" + name);
            return;
        }

        String value = "remove-cookie-" + name;
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(0);
        cookie.setHttpOnly(false);
        response.addCookie(cookie);
    }

    public static void addCookie(HttpServletResponse response, String name, String value, Integer expiry) {
        if (null == response) {
            log.error("#734 addCookie error, response=" + response + ", name=" + name + ", value=" + value);
            return;
        }

        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        if (null != expiry) {
            cookie.setMaxAge(expiry);
        }

        response.addCookie(cookie);
    }

    public static void invalidateCookie(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = getRequestCookies(request);
        if (ArrayUtil.isEmpty(cookies)) {
            return;
        }

        for (Cookie cookie : cookies) {
            if (null != cookie) {
                String name = cookie.getName();
                removeCookie(response, name);
            }
        }
    }

    public static void invalidateCookie() {
        HttpServletRequest request = getRequest();
        HttpServletResponse response = getResponse();
        invalidateCookie(request, response);
    }

    public static Cookie getRequestCookie(String name) {
        HttpServletRequest request = getRequest();
        return getRequestCookie(request, name);
    }

    public static String getRequestCookieValue(String name) {
        Cookie cookie = getRequestCookie(name);
        return null == cookie ? null : cookie.getValue();
    }

    public static String getRequestCookieValue(HttpServletRequest request, String name) {
        Cookie cookie = getRequestCookie(request, name);
        return null == cookie ? null : cookie.getValue();
    }

    public static Cookie[] getRequestCookies(HttpServletRequest request) {
        if (null == request) {
            log.error("#598 getRequestCookies error, request is null");
            return null;
        }

        return request.getCookies();
    }

    public static Cookie[] getRequestCookies() {
        HttpServletRequest request = getRequest();
        return getRequestCookies(request);
    }

    public static Cookie getRequestCookie(HttpServletRequest request, String name) {
        Cookie[] cookies = getRequestCookies(request);

        if (null == cookies) {
            return null;
        }

        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }

        return null;
    }

    public static Integer getRequestCookieValueInteger(String name) {
        return getRequestCookieValueInteger(name, null);
    }

    public static Integer getRequestCookieValueInteger(String name, Integer defaultValue) {
        String value = getRequestCookieValue(name);

        if (StringUtil.isEmpty(value) || value.trim().isEmpty() || "null".equalsIgnoreCase(value)) {
            return defaultValue;
        }

        try {
            return new Integer(value);
        } catch (Throwable e) {
            String message = "#772 getRequestCookieValueInteger error, name=" + name + ", value=" + value //
                    + ", UserAgent=" + getUserAgent() + ", RemoteAddr=" + getRemoteAddr() //
                    + ", ServerName=" + getServerName() + ", RequestURI=" + getRequestURI() //
                    + ", e=" + e;

            log.error(message, e);

            throw new RuntimeException(message);
        }
    }

    /**
     * Content-disposition: attachment;
     * filename="6PKLToWKRJfkdiEggo_IoRo4pI24vQzDk89VtxCqHOF59NkmEsEJpayrn4_BAirJ.jpg"
     * Content-disposition: attachment; filename="MEDIA_ID.jpg"
     */
    public static String getFilenameFromContentDisposition(String contentDisposition) {
        if (StringUtil.isEmpty(contentDisposition)) {
            return null;
        }

        String fromString = "filename=\"";
        int fromStringLength = fromString.length();
        int fromIndex = contentDisposition.indexOf(fromString);
        if (fromIndex < 1) {
            return null;
        }

        int fromStringEndIndex = fromIndex + fromStringLength;
        int engIndex = contentDisposition.indexOf("\"", fromStringEndIndex);

        if (engIndex >= 0) {
            return contentDisposition.substring(fromStringEndIndex, engIndex);
        }

        return contentDisposition.substring(fromStringEndIndex);
    }
}
